<?php
namespace App\Wen\Utils;
use App\Lib\Uploads\UploadHandler;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Intervention\Image\Facades\Image;
use Milon\Barcode\DNS1D;
use Qcloud\Cos\Client;
use SimpleSoftwareIO\QrCode\Facades\QrCode;


class ImageUtils{

    public static function get_url_img_info($url){
        $img_info = json_decode(Cache::get($url, '[]'), true);
        if($img_info && _array_key($img_info, 'width', 0) > 0){
            return ['width'=>_array_key($img_info, 'width', 0), 'height'=>_array_key($img_info, 'height', 0)];
        }

        try {
            list($img_width, $img_height, $type, $attr) = getimagesize($url);
            if($img_width > 0 && $img_height > 0){
                return ['width'=>$img_width, 'height'=>$img_height];
            }
            return null;
        }catch (\Exception $e){
            return null;
        }

    }

    public static function  find_closed_color($colors, $targetColor){
        $closestColor = null;
        $closestDistance = INF;

        foreach ($colors as $color) {

            $rDiff = $color[0] - $targetColor[0];
            $gDiff = $color[1] - $targetColor[1];
            $bDiff = $color[2] - $targetColor[2];

            $distance = sqrt($rDiff * $rDiff + $gDiff * $gDiff + $bDiff * $bDiff);
            if ($distance < $closestDistance) {
                $closestDistance = $distance;
                $closestColor = $color;
            }
        }
        return $closestColor;
    }

    public static function upload_video_screenshot($video_url){

        $attachment = FileUtils::get_url_attach($video_url);
        if(_empty_($attachment)){
            return null;
        }
        if($attachment->cos_review !== 0){
            return null;
        }

        $video_url_parse = parse_url($video_url);
        $file_name = mini_rand(1000000, 99999999) . '_' . time() . ".jpg";
        $save_img_path = self::tmp_image_dir() . $file_name;
        $ossType = Settings::get('ossType');

        // 腾讯云cos
        if ($ossType == 'cosv5') {
            $cosConfig = Settings::get('cosv5', []);
            $cosClient = new Client(array(
                'region' => $cosConfig['region'],
                'credentials' => array(
                    'secretId' => $cosConfig['secretId'],
                    'secretKey' => $cosConfig['secretKey'],
                )
            ));
            ### 获取截屏
            try {
                $result = $cosClient->getSnapshot(array(
                    'Bucket' => $cosConfig['bucket'] . '-' . $cosConfig['appId'],
                    'Key' => $video_url_parse['path'],
                    'ci-process' => 'snapshot',
                    'Time' => Settings::get('video_snapshot_time', 3, true),
                    'SaveAs' => $save_img_path
                ));
                if ($result) {
                    $path = UploadHandler::handle(new UploadedFile($save_img_path, $file_name));
                    unlink($save_img_path);
                    return $path;
                }
            } catch (\Exception $e) {
                _logger_(__file__, __line__, $e->getMessage());
                return null;
            }
        }
        _logger_(__file__, __line__, '非正常结束, 不支持的存储类型：'.$ossType);
        return null;
    }

    /** 上传url图片至cos
     * @param $url
     * @param string $img_name
     * @param array $cut
     * @param array $sizes 宽,高
     * @param bool $remove_local
     * @return array|null
     */
    public static function upload_url_img($url, $img_name = '', $cut = [], $sizes = [], $remove_local = true, $uid = 0, $img_state = 1, $scene = 0){
        $res = self::download_url_img($url, $img_name, $cut, true);
        if($res['code'] == 1){
            if($sizes && isset($sizes[0]) && isset($sizes[1])){
                self::image_cropper($res['local_path'], $res['local_path'], $sizes[0], $sizes[1]);
            }
            $path = UploadHandler::handle($res['upload_file_obj'], $uid, $img_state, $scene, $img_name);
            if($remove_local){
                @unlink($res['local_path']);
            }
            return $path;
        }
        return null;
    }

    /** 下载网络图片，并且可以简单的裁剪四周
     * @param $url
     * @param string $img_name
     * @param array $cut
     * @param false $uploaded_file_obj
     * @return array
     */
    public static function download_url_img($url, $img_name = '', $cut = [], $uploaded_file_obj = false){

        $err_msg = ['code'=>0, 'msg'=>'', 'local_path'=>'', 'upload_file_obj'=>null];

        if(_empty_($url)){
            return $err_msg;
        }

        if(_empty_(self::imgurl_filter($url))){
            return $err_msg;
        }

        $path = self::tmp_image_dir();
        if (!is_dir($path)) {
            mkdir($path, 0755, true);
        }

        $ext = self::url_image_extend($url);

        if(!_empty_($img_name)){
            $file_name = $img_name . "." . $ext;
        }else{
            $file_name = mini_rand(1000000, 99999999) . '_' . time() . "." . $ext; //文件名
        }

        $local_full_name = $path . $file_name;
        $err_msg['local_path'] = $local_full_name;


        try {
            $Referer = '';
            if(strpos($url, 'sinaimg') !== false){
                $Referer = 'Referer: https://weibo.com/';
            }
            $opts = array(
                'http' => array(
                    'method' => "GET",
                    'timeout' => 5,
                    'header' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36;'.$Referer
                ),
                "ssl" => [
                    "verify_peer"=>false,
                    "verify_peer_name"=>false,
                ]
            );
            $url = str_replace('\\', '/', $url);
            $context = stream_context_create($opts);
            $img_data = @file_get_contents($url, false, $context);
            if (!$http_response_header || (strpos($http_response_header[0], '200') === false && strpos($http_response_header[0], '301') === false && strpos($http_response_header[0], '302') === false)) {
                _logger_(__file__, __line__, '图片下载错误：'.$url);
                $err_msg['msg'] = '图片下载错误：'.$url;
                return $err_msg;
            }

            if(strpos($img_data, 'WEBP') !== false || $ext == 'webp'){
                // 处理 不了
                $fp2 = @fopen($local_full_name, 'a');
                fwrite($fp2, $img_data);
                fclose($fp2);

                $err_msg['code'] = 1;
                if($uploaded_file_obj){
                    $err_msg['upload_file_obj'] =  new UploadedFile($local_full_name, $file_name);
                }
                return $err_msg;

            }else if($ext == 'gif'){
                $fp2 = @fopen($local_full_name, 'a');
                fwrite($fp2, $img_data);
                fclose($fp2);
                $err_msg['code'] = 1;
                if($uploaded_file_obj){
                    $err_msg['upload_file_obj'] = new UploadedFile($local_full_name, $file_name);
                }
                return $err_msg;
            }else{
                $src_img = @imagecreatefromstring($img_data);
            }
        }catch (\Exception $e){
            _logger_(__file__, __line__, '下载图片出现错误：'.$url);
            $err_msg['msg'] = '下载图片出现错误：'.$url;
            return $err_msg;
        }

        if(_empty_($cut)){
            $fp3 = @fopen($local_full_name, 'a');
            fwrite($fp3, $img_data);
            fclose($fp3);
            $err_msg['code'] = 1;
            if($uploaded_file_obj){
                $err_msg['upload_file_obj'] = new UploadedFile($local_full_name, $file_name);
            }
            return $err_msg;
        }


        if(file_exists($local_full_name)){
            $info = getimagesize($local_full_name);
        }else{
            $info = @getimagesize($url);
            if(_empty_($info)){
                $fp3 = @fopen($local_full_name.'_', 'a');
                fwrite($fp3, $img_data);
                fclose($fp3);
                $info = getimagesize($local_full_name.'_');
                unlink($local_full_name.'_');
            }
        }

        if(_empty_($info)){
            $fp4 = @fopen($local_full_name, 'a');
            fwrite($fp4, $img_data);
            fclose($fp4);
            $err_msg['code'] = 1;
            if($uploaded_file_obj){
                $err_msg['upload_file_obj'] = new UploadedFile($local_full_name, $file_name);
            }
            return $err_msg;
        }

        $water_width =  $cut['w'] ?? 0;
        $water_height =  $cut['h'] ?? 0;

        $w = $info[0];
        $h = $info[1];

        $origin_start_x = 0;
        $origin_start_y = 0;
        if ($water_width == 0) {
            $new_width = $w;
        } elseif ($water_width > 0) {
            $origin_start_x = $water_width;
            $new_width = $w - $water_width;
        } elseif ($water_width < 0) {
            $new_width = $w + $water_width;
        }
        if ($water_height == 0) {
            $new_height = $h;
        } elseif ($water_height > 0) {
            $origin_start_y = $water_height;
            $new_height = $h - $water_height;
        } elseif ($water_height < 0) {
            $new_height = $h + $water_height;
        }


        $ratio = 1;
        $inter_w = (int)($new_width / $ratio);
        $inter_h = (int)($new_height / $ratio);

        if($inter_w > 0 && $inter_h > 0){
            try {
                $new_img = @imagecreatetruecolor($inter_w, $inter_h);
                if($new_img){
                    @imagecopy($new_img, $src_img, 0, 0, $origin_start_x > 0 ? $origin_start_x : 0, $origin_start_y > 0 ? $origin_start_y : 0, $inter_w, $inter_h);
                }else{
                    _logger_(__file__, __line__, 'imagecreatetruecolor函数出错。');
                    $err_msg['msg'] = 'imagecreatetruecolor函数出错。';
                    return $err_msg;
                }
            }catch (\Exception $e){
                _logger_(__file__, __line__, $e->getMessage());
                $err_msg['msg'] = $e->getMessage();
                return $err_msg;
            }
        }else{
            $err_msg['msg'] = '$inter_w || $inter_h 小于等于0';
            return $err_msg;
        }
        $aa = @imagepng($new_img, $local_full_name);
        if ($aa) {
            $err_msg['code'] = 1;
            if($uploaded_file_obj){
                $err_msg['upload_file_obj'] = new UploadedFile($local_full_name, $file_name);
            }
            return $err_msg;
        } else {
            $err_msg['msg'] = 'imagepng失败';
            return $err_msg;
        }

    }

    /** 获取本地图片的缩略图
     * @param $source_path
     * @param $save_path
     * @param $target_width
     * @param $target_height
     * @return mixed|null
     */
    public static function image_cropper($source_path, $save_path, $target_width, $target_height)
    {
        $source_info = getimagesize($source_path);
        $source_width = $source_info[0];
        $source_height = $source_info[1];
        $source_mime = $source_info['mime'];
        $source_ratio = $source_height / $source_width;
        $target_ratio = $target_height / $target_width;
        if ($target_height > $source_height) {
            $target_height = $source_height;
            $target_width = intval($target_height / $target_ratio);
        }
        if ($target_width > $source_width) {
            $target_width = $source_width;
            $target_height = intval($target_width * $target_ratio);
        }
        // 源图过高
        if ($source_ratio > $target_ratio) {
            $cropped_width = $source_width;
            $cropped_height = $source_width * $target_ratio;
            $source_x = 0;
            $source_y = ($source_height - $cropped_height) / 2;
        }
        // 源图过宽
        elseif ($source_ratio < $target_ratio) {
            $cropped_width = $source_height / $target_ratio;
            $cropped_height = $source_height;
            $source_x = ($source_width - $cropped_width) / 2;
            $source_y = 0;
        }
        // 源图适中
        else {
            $cropped_width = $source_width;
            $cropped_height = $source_height;
            $source_x = 0;
            $source_y = 0;
        }
        switch ($source_mime) {
            case 'image/gif':
                $source_image = imagecreatefromgif($source_path);
                break;

            case 'image/jpeg':
                $source_image = imagecreatefromjpeg($source_path);
                break;

            case 'image/png':
                $source_image = imagecreatefrompng($source_path);
                break;

            default:
                return null;
        }
        $target_image = imagecreatetruecolor($target_width, $target_height);
        $cropped_image = imagecreatetruecolor($cropped_width, $cropped_height);
        //裁剪
        imagecopy($cropped_image, $source_image, 0, 0, $source_x, $source_y, $cropped_width, $cropped_height);
        // 缩放
        imagecopyresampled($target_image, $cropped_image, 0, 0, 0, 0, $target_width, $target_height, $cropped_width, $cropped_height);
        //临时保存到本地
        $aa = imagepng($target_image, $save_path);
        if ($aa) {
            return $save_path;
        }
        return null;
    }


    private static function tmp_image_dir(){
        return storage_path('tmp/images/');
    }

    private static function url_image_extend($url)
    {
        if (strpos($url, '.png')) {
            return 'png';
        } else if (strpos($url, '.jpg')) {
            return 'jpg';
        } else if (strpos($url, '.jpeg')) {
            return 'jpeg';
        } else if (strpos($url, '.gif')) {
            return 'gif';
        } else if (strpos($url, '.heic')) {
            return 'heic';
        } else {
            return 'jpg';
        }
    }




    private static function imgurl_filter($url){
        if(_empty_($url)){
            return '';
        }
        if (strpos($url, 'emot') !== false) {
            return '';
        }
        if(strpos($url,'face')!==false){
            return '';
        }
        if(strpos($url,'smile')!==false){
            return '';
        }
        return $url;
    }

    /**
     * 判断图片是否主要是白色或类似白色。
     *
     * @param string $path 图片路径
     * @param float $threshold 判断为主要白色的阈值比例 (0 到 1 之间)
     * @param int $tolerance 白色的容差范围 (0 到 255 之间)
     * @return bool
     */
    public static function is_mostly_white($path, $threshold = 0.7, $tolerance = 50)
    {
        // 加载图片
        if(strpos($path, 'http') === 0){
            $image = Image::make(file_get_contents($path));
        }else{
            $image = Image::make($path);
        }

        // 获取图像的宽度和高度
        $width = $image->width();
        $height = $image->height();

        // 统计白色或接近白色的像素数
        $whitePixelCount = 0;
        $totalPixelCount = $width * $height;

        // 遍历每个像素
        for ($x = 0; $x < $width; $x++) {
            for ($y = 0; $y < $height; $y++) {
                $color = $image->pickColor($x, $y, 'array');
                if (self::is_white_or_near_white($color, $tolerance)) {
                    $whitePixelCount++;
                }
            }
        }

        // 计算白色或接近白色像素的比例
        $whiteRatio = $whitePixelCount / $totalPixelCount;

        // 判断是否主要是白色
        return $whiteRatio >= $threshold;
    }

    /**
     * 判断颜色是否是白色或接近白色。
     *
     * @param array $color RGB 颜色数组
     * @param int $tolerance 容差范围 (0 到 255 之间)
     * @return bool
     */
    private static function is_white_or_near_white($color, $tolerance)
    {
        // 白色的 RGB 值是 (255, 255, 255)
        $white = [255, 255, 255];

        // 判断颜色是否在白色的容差范围内
        return _abs($color[0] - $white[0]) <= $tolerance &&
            _abs($color[1] - $white[1]) <= $tolerance &&
            _abs($color[2] - $white[2]) <= $tolerance;
    }


    public static function get_img_base64($url, $roate = 0, $width = 400, $height = 400){
        if(_empty_($url)){
            return null;
        }
        try {
            $response = Http::get($url . '?imageMogr2/quality/100/format/png/interlace/0/crop/'.$width.'x'.$height.'/gravity/center/thumbnail/'.$width.'x');
            if (!$response->successful()) {
                return null;
            }
            return (string)(Image::make($response->body())->rotate(-$roate)->encode('data-url'));
        } catch (\Exception $e) {
            // 异常处理
            return null;
        }
    }


    public static function code($content, $type = 'qr', $size = 200){

        try {
            if($type == 'qr'){
                $content = QrCode::format('png')->size($size)->generate($content);
            }else if($type = 'bar'){
                $barcode = new DNS1D();
                $content = base64_decode($barcode->getBarcodePNG($content, 'C128'));
            }
            $res = UploadHandler::binary($content, 'png');
            if(_array_key($res, 'url', '')){
                return _array_key($res, 'url', '');
            }else{
                _logger_(__file__, __line__, '生成条形码失败');
                return null;
            }
        }catch (\Exception $e){
            _logger_(__file__, __line__, $e->getMessage());
            return null;
        }
    }


}
